Release 10.1A: OpenEdge Development:
Progress 4GL Handbook
DO blocks
A
DOblock is the most basic programming block in the 4GL. The keywordDOstarts a block of statements without doing anything else with those statements except grouping them, unless you tell it to. You’ve already used the keywordDOas a block header in a couple of ways, including your trigger blocks, such as this trigger on the Next button inh-CustOrderWin1.w:
This block only assures that all the statements are executed together when the event occurs. If you take a closer look at this trigger, you can use another
DOblock inside it to correct a small error in the program logic.
![]()
To see the error in the program logic:
There is no next Customer, so the Customer record is not changed. The
IF AVAILABLE Customerphrase in the Next button trigger assures that nothing happens if there is no Customer to display. However, the preprocessor{&OPEN-BROWSERS-IN-QUERY-CustQuery}, which opens the Order query, isn’t affected by theIF AVAILABLE Customercheck, because it’s a separate statement. So the code opens the Order query even if there’s no current Customer, and therefore displays nothing, as shown in Figure 6–4.Figure 6–4: Example of empty query result
![]()
If there’s no Customer you shouldn’t open the Order query, so you need to bring both statements into the code that is executed only when a Customer is available.
![]()
To correct the statement that opens the query:
- Create another
DO-ENDblock in the trigger:
Now the statement that opens the query won’t execute either if there’s no Customer. This is another illustration of how to use the
DOblock as a way to group multiple statements together, so that they all execute together or not at all. As this example illustrates, you can nestDOblocks as much as you wish.When you enter this code in the Section Editor, the edit control recognizes the keyword
DOfollowed by a colon and automatically adds the matchingENDstatement. Just move this statement to where it belongs at the end of the new block. The editor generally matches the indentation ofENDstatements correctly with the start of the block. Make sure you indent all the statements in the block properly so that someone reading your code can easily see how the logic is organized. It’s also a good idea to get into the habit of always putting a comment with eachENDstatement to clarify which block it’s ending. When your code gets complex enough that a single set of nested blocks takes up more than a page, you’ll be grateful you did this. It can prevent all sorts of logic errors.- Make this same
DO-ENDcorrection to the trigger code for the Prev button.- Save the window as
h-CustOrderWin2.w.The
DOblock is considered the most basic kind of block because Progress doesn’t provide any additional services to the block by default. There is no automatic looping within the block, no record reading, and no other special processing done for you behind the scenes. However, you can get aDOblock to provide some of these services by adding keywords to theDOstatement. The following section provides some examples.Looping with a DO block
If you want to loop through a group of statements some specific number of times, use this form of the
DOstatement:
The following example adds up the integers from one through five and displays the total:
Figure 6–5 shows the result.
Figure 6–5: Result of looping with a DO block
![]()
The starting and ending values can be expressions and not just constants. You can use some value other than one to increment the starting value each time through the loop by using the
BYphrase at the end. If the start and end values are variables or other expressions, Progress evaluates them just once, at the beginning of the first iteration of the block. If the values change inside the block, that doesn’t change how many times the block iterates. For example, the following variation uses the variable that holds the total as the starting expression, after giving it an initial value of one using theINIT(orINITIAL) phrase at the end of the definition:
When you run this procedure, the changes to the variable
iTotalinside the loop don’t affect how the loop executes. The final total is one greater than it was before, as shown in Figure 6–6, only because the initial value of the variable is one instead of the default of zero.Figure 6–6: Example of looping with a DO block with initial value set to 1
![]()
If you want to loop through a group of statements for as long as some logical condition is true, you can use this form of the
DOblock:
For the expression, you can use any combination of constants, operators, field names, and variable names that yield a logical (true/false) value. For example:
By its very nature, the
DO WHILEstatement must evaluate its expression each time through the loop. Otherwise, it would not be able to determine when the condition is no longer true. In this case the variableiTotal, which starts out at one and is doubled until the conditioniTotalis less than 50, is no longer true. So what do you expect the final total to be? 32? Not for this code, as shown in Figure 6–7.Figure 6–7: Example DO WHILE loop result
![]()
The reason for this is that Progress evaluates the expression at the beginning of each iteration. As long as it’s true at that time, the iteration proceeds to the end of the block. At the beginning of the final iteration,
iTotalequals 32, so the condition is still true. During that iteration it is doubled one last time to 64. At the beginning of the next iteration the condition 64 < 50 is no longer true, and the block terminates.When you write a
DO WHILEblock, make sure that there is always a condition that terminates the block. If the condition is true forever, Progress goes into an infinite loop. If this should happen, press CTRL+BREAK on the keyboard to interrupt Progress so that you can go back and correct your mistake.Using a DO block to scope records and frames
You’ll learn more about record scoping in Chapter 7, " Record Buffers and Record Scope." It’s helpful to cover all the syntax forms that can affect it before discussing the meaning of record scope in different situations. For now, you can scope or associate records in one or more tables with a
DOblock by using theFORphrase:
Each
recordnames a record you want to work with in the block and scopes it to the block. References within that block to fields the record contains are automatically associated with that record.You have already seen an example of frame scoping in the code in the
enable_UIprocedure ofh-CustOrderWin2.wand in the button triggers you created based on that code:
You can use the phrase
WITH FRAMEframe-nameand, optionally,IN WINDOWwindow-nameto identify which frame you’re talking about when you display fields or take other actions on objects in frames. If you wish, you can scope all the statements in aDOblock with a frame by appending theWITH FRAMEphrase to theDOstatement itself. For example, here’s theBtnNexttrigger block again with the frame qualifier moved to theDOstatement:
Whether you name the frame in individual statements or in the block header, this makes sure that Progress understands that you want the fields displayed in the frame where you defined them. If you don’t do this, then depending on the context, Progress might display the fields in a different frame.
![]()
To see the result of not explicitly defining a frame scope:
What happened here? Since the
DISPLAYstatement wasn’t qualified with any indication of where to display the fields, Progress created a brand new frame, laid out the fields in it, and displayed it on top of the other frame in your window. To keep this from happening, make sure that all statements that deal with frames are always clear about where actions should take place. The AppBuilder and the other tools take care of this for you most of the time, but when you add code of your own to procedures, you might need to qualify it with the frame name. Otherwise, Progress displays objects in the frame that is scoped to the nearest enclosing block that defines a frame. If there is no explicit frame definition, then you get the result you just saw here. Progress displays the data in an unnamed default frame. Except in the simplest test procedures, like the procedures this book uses to demonstrate the looping syntax, you never want to use the default frame in your applications.There are other phrases you can use to qualify a
DOblock, but they mostly deal with transactions and error handling, which you’ll learn about in Chapter 17, " Managing Transactions."
|
Copyright © 2005 Progress Software Corporation www.progress.com Voice: (781) 280-4000 Fax: (781) 280-4095 |